home *** CD-ROM | disk | FTP | other *** search
-
- #!/usr/local/bin/perl
- #
- # switch to nobody if we are root
- ($<,$>) = (-2,-2) unless $>;
-
- require 'getopts.pl';
-
- #
- # Simple gopher2nntp server. You can change the following variables.
- # nntp_port is hardcoded here since this is a stateless server and
- # no sense in reading it from /etc/services every time...
- #
- # A server that sticks around might be better...
- #
- # Note: The NNTP daemon must accept the XHDR command.
- #
- #
- # You should run "gopher2nntp -g" from cron to generate the groups
- # file. If you don't generate the groups file then this server will
- # grab it from the NNTP server, but thats a waste of time.
- #
- #
- $nntp_server = "leland.stanford.edu";
- $nntp_port = 119;
- $nntp_groups = "/usr/local/etc/newsgroups.gopher"; # could be active file
-
- @nntp_acl=(
- # ipaddress group access + = allow, - = deny
- '^36\. .* +',
- '.* ^clari -',
- '.* .* +'
- );
-
- #
- # Commands this server responds to:
- #
- # "" -> list top level groups
- # ls $group -> list group's articles and sub-groups
- # article $group $number -> get 1 article
- # sorry -> send sorry message
- #
-
- $port=&my_port(); # port this script is running on
- chop($host = `hostname`);
-
- &Getopts('nrdga:s:');
-
- if ($errs || $#ARGV!=-1) {
-
- print<<EOF;
-
- Usage: $0 [-s server] [-a active_file] [-n] [-g] [-d] [-r]
- -s server NNTP server to contact
- -a file Active file to use
- -n Don't use active file
- -g generate new active file
- -d turn on debug (when typing commands from a tty)
- -r list articles in reverse order
- EOF
- exit;
-
- }
-
- $nntp_server = $opt_s if (defined($opt_s));
- $nntp_port = $opt_p if (defined($opt_p));
- $nntp_groups = $opt_a if (defined($opt_a));
-
- &create_groups($opt_g) if defined($opt_g);
-
- $_ = <STDIN>; s/\r//; s/\n//;
-
- &do_ls("") if /^$/;
- &do_ls($1) if /^ls\s+(.*)/i;
- &do_article($1,$2) if /^article\s+(\S+)\s+(\d+)/i;
- &do_sorry if /^sorry$/;
- &reply("3Unknown command!");
- exit;
-
- sub do_article {
- local($group,$number) = @_;
-
- if (&check_access($group) eq '-') {
- &do_sorry;
- &reply(".");
- exit;
- }
-
- &open_nntp;
-
- &send("GROUP $group");
- $_ = &recv;
- &death if !/^211/;
-
- &send("ARTICLE $number");
- $_ = &recv;
- &death if !/^220/;
-
- while(<SERVER>) {
- print;
- last if /^\.\r\n$/;
- }
-
- &close_nntp;
- exit;
- }
-
- sub list_group {
- local($group) = @_;
-
- &send("GROUP $group");
- $_ = &recv;
- &death if !/^211/;
-
- ($n,$f,$l) = /211\s+(\d+)\s+(\d+)\s+(\d+)/;
-
- &send("XHDR Subject $f-$l");
- $_ = &recv;
- &death if !/^221/;
-
- while(<SERVER>) {
- chop; chop;
- last if /^\.$/;
- ($article,$subject) = /^(\d+)\s+(.*)/;
- $subject =~ s/\t/ /g; # just in case!
- if (defined($opt_r)) {
- push(@reply,"0$subject\tarticle $group $article\t$host\t$port");
- } else {
- &reply("0$subject\tarticle $group $article\t$host\t$port");
- }
- }
-
- if (defined($opt_r)) {
- for ($i=$#reply; $i!= -1; $i--) { &reply($reply[$i]); }
- }
-
- &reply(".");
- &close_nntp;
- exit;
- }
-
-
- sub do_ls {
- local($prefix) = @_;
-
- if (&check_access($prefix) eq '-') {
- &reply("0Sorry! No no access off of campus!\tsorry\t$host\t$port");
- &reply(".");
- exit;
- }
-
- &open_nntp;
- &get_groups;
-
- foreach ( sort @groups) {
- if ($_ eq $prefix) { $do_list_group = $_; }
- elsif (/^$prefix\.([^.]*)\.?/) {
- $leaf=$1;
- $save{"$prefix.$leaf"} = "1$leaf\tls $prefix.$leaf\t$host\t$port";
- }
- elsif ($prefix eq '' && /([^.]*)/) {
- $save{"$1"} = "1$1\tls $1\t$host\t$port";
- }
- }
-
- foreach ( sort keys %save) { &reply($save{$_}); }
- &list_group($do_list_group) if ($do_list_group);
-
- &reply(".");
- &close_nntp;
- exit;
- }
-
- sub open_nntp {
- local($_);
- &open_server($nntp_server,$nntp_port);
- $_ = &recv;
- &death if !/^2/;
- }
-
- sub close_nntp {
- &send("QUIT");
- close(SERVER);
- }
-
- sub my_port {
- return -1 if (-t STDIN);
- $sockaddr = 'S n a4 x8';
- $mysockaddr = getsockname(STDIN);
- ($myfamily,$myport,$myaddr) = unpack($sockaddr,$mysockaddr);
- return $myport;
- }
-
- sub open_server {
-
- local($server,$port) = @_;
- $sockaddr = 'S n a4 x8';
- (($name, $aliases, $type, $len, $saddr) = gethostbyname($server))||&death;
- $sin = pack($sockaddr, 2, $port, $saddr);
- socket(SERVER, 2, 1, 0) || &death;
- connect(SERVER, $sin) || &death;
- select(SERVER); $| = 1; select(STDOUT); $| = 1;
-
- }
-
- sub send {
- print "send -> |$_[0]|\n" if (defined($opt_d));
- print SERVER "$_[0]\r\n";
- }
-
- sub recv {
- local ($_);
- $_= <SERVER>;
- chop; chop;
- print "recv -> |$_|\n" if (defined($opt_d));
- return $_;
- }
-
- sub reply { print "$_[0]\r\n";}
- sub death { &reply("."); exit; }
-
- sub get_groups {
- if (!defined($opt_n) && open(GROUPS,$nntp_groups)) {
- while(<GROUPS>) {
- chop;
- ($grp) = /^(\S+)/;
- push(@groups,$grp);
- }
- close(GROUPS);
- } else { # can't open file, get list from server!
- &load_groups;
- }
- }
-
- sub load_groups {
-
- &open_nntp;
- &send("LIST");
- $_ = &recv;
- &death if !/^215/;
-
- while(<SERVER>) {
- chop; chop;
- last if /^\.$/;
- s/^(\S+).*/$1/;
- push(@groups,$_);
- }
-
- }
-
- sub create_groups {
-
- &load_groups;
-
- open(GROUPS,">$nntp_groups") || die "$nntp_groups: $!";
- foreach (@groups) { print GROUPS "$_\n"; }
- close GROUPS;
-
- &close_nntp;
- exit;
- }
-
- sub check_access {
- local($group)=@_;
-
- return 1 if (-t STDIN);
- $sockaddr = 'S n a4 x8';
- $mysockaddr = getpeername(STDIN);
- ($ramily,$rport,$raddr) = unpack($sockaddr,$mysockaddr);
- ($a,$b,$c,$d) = unpack('C4',$raddr);
- $ipaddress = "$a.$b.$c.$d";
-
- foreach (@nntp_acl) {
- ($ipacl,$groupacl,$access)=split;
- return $access if ($ipaddress =~ /$ipacl/) && ($group =~ /$groupacl/);
- }
- return '-'; #default is to restrict access
- }
-
- sub do_sorry {
-
- print<<EOF;
-
- Sorry! You have selected information that cannot be delivered off
- of campus due to restrictions.
-
- -- The Mole Hole Guardian
-
- EOF
-
- &reply(".");
- exit;
-
- }
-